<!DOCTYPE html>





<html class="theme-next muse use-motion" lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="generator" content="Hexo 3.9.0">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=7.3.0">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=7.3.0">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=7.3.0">
  <link rel="mask-icon" href="/images/logo.svg?v=7.3.0" color="#222">

<link rel="stylesheet" href="/css/main.css?v=7.3.0">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">


<script id="hexo-configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Muse',
    version: '7.3.0',
    exturl: false,
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false},
    back2top: {"enable":true,"sidebar":false,"scrollpercent":false},
    save_scroll: false,
    copycode: {"enable":false,"show_result":false,"style":null},
    fancybox: false,
    mediumzoom: false,
    lazyload: false,
    pangu: false,
    algolia: {
      appID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    },
    localsearch: {"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},
    path: '',
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    translation: {
      copy_button: '复制',
      copy_success: '复制成功',
      copy_failure: '复制失败'
    }
  };
</script>

  <meta name="description" content="编码规范https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/ 禁止拷贝基类为什么禁用拷贝（复制）构造函数 浅拷贝问题  默认生成的拷贝构造函数会直接拷贝成员指针的地址，这样两个对象的指针指向同一个缓冲区，导致析构的时候两次删除同一片区域的问题（这个问题又叫双杀问题）  解决办法：  自己编写拷贝构造">
<meta name="keywords" content="C++11">
<meta property="og:type" content="article">
<meta property="og:title" content="C++常用工具类">
<meta property="og:url" content="http://yoursite.com/2019/07/01/C++常用工具类/index.html">
<meta property="og:site_name" content="XuQi&#39;s Blog">
<meta property="og:description" content="编码规范https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/ 禁止拷贝基类为什么禁用拷贝（复制）构造函数 浅拷贝问题  默认生成的拷贝构造函数会直接拷贝成员指针的地址，这样两个对象的指针指向同一个缓冲区，导致析构的时候两次删除同一片区域的问题（这个问题又叫双杀问题）  解决办法：  自己编写拷贝构造">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2019-10-20T13:23:23.037Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="C++常用工具类">
<meta name="twitter:description" content="编码规范https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/ 禁止拷贝基类为什么禁用拷贝（复制）构造函数 浅拷贝问题  默认生成的拷贝构造函数会直接拷贝成员指针的地址，这样两个对象的指针指向同一个缓冲区，导致析构的时候两次删除同一片区域的问题（这个问题又叫双杀问题）  解决办法：  自己编写拷贝构造">
  <link rel="canonical" href="http://yoursite.com/2019/07/01/C++常用工具类/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome: false,
    isPost: true,
    isPage: false,
    isArchive: false
  };
</script>

  <title>C++常用工具类 | XuQi's Blog</title>
  








  <noscript>
  <style>
  .use-motion .motion-element,
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-title { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  <div class="container sidebar-position-left">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta">

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">XuQi's Blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
      
      
      
        
        <li class="menu-item menu-item-home">
      
    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
      
      
      
        
        <li class="menu-item menu-item-archives">
      
    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
  </ul>

    

</nav>
</div>
    </header>

    


    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content page-post-detail">
            

  <div id="posts" class="posts-expand">
    

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2019/07/01/C++常用工具类/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="XuQi">
      <meta itemprop="description" content="">
      <meta itemprop="image" content="/images/avatar.gif">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="XuQi's Blog">
    </span>
      <header class="post-header">

        
          <h1 class="post-title" itemprop="name headline">C++常用工具类

            
          </h1>
        

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              
                
              

              <time title="创建时间：2019-07-01 22:41:57" itemprop="dateCreated datePublished" datetime="2019-07-01T22:41:57+00:00">2019-07-01</time>
            </span>
          
            

            
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2019-10-20 13:23:23" itemprop="dateModified" datetime="2019-10-20T13:23:23+00:00">2019-10-20</time>
              </span>
            
          

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h4 id="编码规范"><a href="#编码规范" class="headerlink" title="编码规范"></a>编码规范</h4><p><a href="https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/" target="_blank" rel="noopener">https://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styleguide/</a></p>
<h4 id="禁止拷贝基类"><a href="#禁止拷贝基类" class="headerlink" title="禁止拷贝基类"></a>禁止拷贝基类</h4><h5 id="为什么禁用拷贝（复制）构造函数"><a href="#为什么禁用拷贝（复制）构造函数" class="headerlink" title="为什么禁用拷贝（复制）构造函数"></a>为什么禁用拷贝（复制）构造函数</h5><ul>
<li><p>浅拷贝问题</p>
<blockquote>
<p>默认生成的拷贝构造函数会直接拷贝成员指针的地址，这样两个对象的指针指向同一个缓冲区，导致析构的时候两次删除同一片区域的问题（这个问题又叫<code>双杀</code>问题）</p>
</blockquote>
<p>解决办法：</p>
<ol>
<li><p>自己编写拷贝构造函数</p>
</li>
<li><p>使用 <code>shared_ptr</code> 这样的智能指针</p>
</li>
<li><p>禁用拷贝构造函数和赋值操作符</p>
<a id="more"></a> 
</li>
</ol>
</li>
<li><p>基类拷贝问题</p>
<blockquote>
<p>如果我们不去自己编写拷贝构造函数，编译器默认生成的版本会自动调用基类的拷贝构造 函数完成基类的拷贝，但是如果我们出于某种原因编写了，自己编写了拷贝构造函数（比如因为上文中提到的浅 拷贝问题），编译器不会帮我们安插基类的拷贝构造函数，它只会在必要的时候帮我们安 插基类的默认构造函数</p>
</blockquote>
</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//禁止拷贝基类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">noncopyable</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line"><span class="keyword">protected</span>: <span class="comment">// 为什么声明成为 protected</span></span><br><span class="line">    noncopyable() &#123;&#125;</span><br><span class="line">    ~noncopyable() &#123;&#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="comment">//禁止拷贝</span></span><br><span class="line">    noncopyable(<span class="keyword">const</span> noncopyable &amp;that) = <span class="keyword">delete</span>;</span><br><span class="line">    noncopyable(noncopyable &amp;&amp;that) = <span class="keyword">delete</span>;</span><br><span class="line">    noncopyable &amp;<span class="keyword">operator</span>=(<span class="keyword">const</span> noncopyable &amp;that) = <span class="keyword">delete</span>;</span><br><span class="line">    noncopyable &amp;<span class="keyword">operator</span>=(noncopyable &amp;&amp;that) = <span class="keyword">delete</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h4 id="StrPrinter-辅助类"><a href="#StrPrinter-辅助类" class="headerlink" title="StrPrinter 辅助类"></a>StrPrinter 辅助类</h4><p>字符串拼接输出</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">string</span> output = StrPrinter &lt;&lt; <span class="string">"a"</span> &lt;&lt; <span class="string">"b"</span> &lt;&lt; <span class="string">"c"</span> &lt;&lt; <span class="string">"d"</span> &lt;&lt; <span class="built_in">endl</span>;</span><br></pre></td></tr></table></figure>

<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> StrPrinter _StrPrinter()</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> _<span class="title">StrPrinter</span> :</span> <span class="keyword">public</span> <span class="built_in">string</span> &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    _StrPrinter() &#123;&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line">    _StrPrinter&amp; <span class="keyword">operator</span> &lt;&lt;(T &amp;&amp; data) &#123; <span class="comment">// 右值引用</span></span><br><span class="line">        _stream &lt;&lt; <span class="built_in">std</span>::forward&lt;T&gt;(data); <span class="comment">// 按照原有的类型转换，不管是const还是非const</span></span><br><span class="line">        <span class="keyword">this</span>-&gt;<span class="built_in">string</span>::<span class="keyword">operator</span>=(_stream.str()); <span class="comment">//调用基类的赋值函数，把值放在内部</span></span><br><span class="line">        <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">string</span> <span class="keyword">operator</span> &lt;&lt;(<span class="built_in">std</span>::ostream&amp;(*f)(<span class="built_in">std</span>::ostream&amp;)) <span class="keyword">const</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="built_in">stringstream</span> _stream;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h4 id="Logger-辅助类"><a href="#Logger-辅助类" class="headerlink" title="Logger 辅助类"></a>Logger 辅助类</h4><h5 id="LogContextCapturer"><a href="#LogContextCapturer" class="headerlink" title="LogContextCapturer"></a>LogContextCapturer</h5><ul>
<li>传入Logger对象，用于实现log输出方式</li>
<li>实现 操作符&lt;&lt;，用于输出log</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  可以有多个Capturer，每个Capture可以logContext，他们使用同一个logger用于输出Log</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LogContextCapturer</span> :</span> <span class="keyword">public</span> noncopyable &#123; <span class="comment">//禁止拷贝构造函数</span></span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  LogContextCapturer(Logger &amp;logger, LogLevel level, <span class="keyword">const</span> <span class="keyword">char</span> *file, <span class="keyword">const</span> <span class="keyword">char</span> *function, <span class="keyword">int</span> line)</span><br><span class="line">      : m_pLogContext(<span class="keyword">new</span> LogContext(level, file, function, line)), m_logger(logger) &#123;&#125;</span><br><span class="line"></span><br><span class="line">  LogContextCapturer &amp;<span class="keyword">operator</span>&lt;&lt;(ostream &amp;(*f)(ostream &amp;)) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!m_pLogContext) &#123;</span><br><span class="line">      <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    m_logger.write(m_pLogContext); <span class="comment">// 将LogContext 的内容传给Logger，并通过Logger传给不同的channel或者writter</span></span><br><span class="line">    m_pLogContext.reset(); <span class="comment">// 清空log的内容</span></span><br><span class="line">    <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line">  LogContextCapturer &amp;<span class="keyword">operator</span>&lt;&lt;(T &amp;&amp;data) &#123;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (!m_pLogContext) &#123;</span><br><span class="line">      <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    (*m_pLogContext) &lt;&lt; <span class="built_in">std</span>::forward&lt;T&gt;(data); <span class="comment">// 将log存到自己的logContext中</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> *<span class="keyword">this</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  LogContextPtr m_pLogContext; <span class="comment">// 用于保存log的内容</span></span><br><span class="line">  Logger &amp;m_logger; <span class="comment">// Log对象的输出</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h5 id="LogContext"><a href="#LogContext" class="headerlink" title="LogContext"></a>LogContext</h5><ul>
<li>继承于ostringstream</li>
<li>保存log的基本信息</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> *  Log的内容</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LogContext</span> :</span> <span class="keyword">public</span> <span class="built_in">ostringstream</span> &#123;</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  <span class="keyword">friend</span> <span class="class"><span class="keyword">class</span> <span class="title">LogContextCapturer</span>;</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  LogLevel m_level;</span><br><span class="line">  <span class="keyword">int</span> m_line;</span><br><span class="line">  <span class="keyword">const</span> <span class="keyword">char</span> *m_pFile;</span><br><span class="line">  <span class="keyword">const</span> <span class="keyword">char</span> *m_pFunction;</span><br><span class="line">  <span class="class"><span class="keyword">struct</span> <span class="title">timeval</span> _<span class="title">tv</span>;</span></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  LogContext(LogLevel level, <span class="keyword">const</span> <span class="keyword">char</span> *file, <span class="keyword">const</span> <span class="keyword">char</span> *function, <span class="keyword">int</span> line)</span><br><span class="line">      : m_level(level),</span><br><span class="line">        m_line(line),</span><br><span class="line">        m_pFile(file),</span><br><span class="line">        m_pFunction(function) &#123;</span><br><span class="line">    gettimeofday(&amp;_tv, <span class="literal">NULL</span>);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h5 id="Logger"><a href="#Logger" class="headerlink" title="Logger"></a>Logger</h5><ul>
<li>可以追加多个Channel</li>
<li>统一调整每个Channel的等级</li>
<li>可以设置writer，如果设置writer，则用writer输出各个Channel，如果没设置，则用默认channel输出</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 每个Logger对象有一个Channel Map 和writer</span></span><br><span class="line"><span class="comment"> * 如果writer为空，则写入channles，否则写入writer</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Logger</span> :</span> <span class="keyword">public</span> <span class="built_in">std</span>::enable_shared_from_this&lt;Logger&gt;, <span class="keyword">public</span> noncopyable &#123;</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"></span><br><span class="line">  <span class="keyword">friend</span> <span class="class"><span class="keyword">class</span> <span class="title">LogContextCapturer</span>;</span></span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">setWriter</span><span class="params">(<span class="keyword">const</span> <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;LogWriter&gt; &amp;writer)</span> </span>&#123;</span><br><span class="line">    m_pWriter = writer;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">setLevel</span><span class="params">(LogLevel level)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;ch : m_ChannelsPoint) &#123;</span><br><span class="line">      ch.second-&gt;setLevel(level);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  </span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">writeChannels</span><span class="params">(<span class="keyword">const</span> LogContextPtr &amp;stream)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;c : m_ChannelsPoint) &#123;</span><br><span class="line">      c.second-&gt;write(*<span class="keyword">this</span>, stream);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">write</span><span class="params">(<span class="keyword">const</span> LogContextPtr &amp;stream)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (m_pWriter) &#123;</span><br><span class="line">      m_pWriter-&gt;write(stream);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      writeChannels(stream);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="built_in">map</span>&lt;<span class="built_in">string</span>, <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;LogChannel&gt; &gt; m_ChannelsPoint;</span><br><span class="line">  <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;LogWriter&gt; m_pWriter;</span><br><span class="line">  <span class="built_in">string</span> m_loggerName;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h5 id="LogChannel"><a href="#LogChannel" class="headerlink" title="LogChannel"></a>LogChannel</h5><ul>
<li>Channel的基类，子类要重写write，需要调用format格式化输出log</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">LogChannel</span> :</span> <span class="keyword">public</span> noncopyable &#123;</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">write</span><span class="params">(<span class="keyword">const</span> Logger &amp;logger, <span class="keyword">const</span> LogContextPtr &amp;stream)</span> </span>= <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> <span class="built_in">std</span>::<span class="function"><span class="built_in">string</span> <span class="title">printTime</span><span class="params">(<span class="keyword">const</span> timeval &amp;tv)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">time_t</span> sec_tmp = tv.tv_sec;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">tm</span> *<span class="title">tm</span> = <span class="title">localtime</span>(&amp;<span class="title">sec_tmp</span>);</span></span><br><span class="line">    <span class="keyword">char</span> buf[<span class="number">128</span>];</span><br><span class="line">    <span class="built_in">snprintf</span>(buf, <span class="keyword">sizeof</span>(buf), <span class="string">"%d-%02d-%02d %02d:%02d:%02d.%03d"</span>,</span><br><span class="line">             <span class="number">1900</span> + tm-&gt;tm_year,</span><br><span class="line">             <span class="number">1</span> + tm-&gt;tm_mon,</span><br><span class="line">             tm-&gt;tm_mday,</span><br><span class="line">             tm-&gt;tm_hour,</span><br><span class="line">             tm-&gt;tm_min,</span><br><span class="line">             tm-&gt;tm_sec,</span><br><span class="line">             (<span class="keyword">int</span>) (tv.tv_usec / <span class="number">1000</span>));</span><br><span class="line">    <span class="keyword">return</span> buf;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span>:</span><br><span class="line">  <span class="comment">// 格式化字符串</span></span><br><span class="line">  <span class="function"><span class="keyword">virtual</span> <span class="keyword">void</span> <span class="title">format</span><span class="params">(<span class="keyword">const</span> Logger &amp;logger,</span></span></span><br><span class="line"><span class="function"><span class="params">                      ostream &amp;ost,</span></span></span><br><span class="line"><span class="function"><span class="params">                      <span class="keyword">const</span> LogContextPtr &amp;logContext,</span></span></span><br><span class="line"><span class="function"><span class="params">                      <span class="keyword">bool</span> enableColor = <span class="literal">true</span>,</span></span></span><br><span class="line"><span class="function"><span class="params">                      <span class="keyword">bool</span> enableDetail = <span class="literal">true</span>)</span></span>;</span><br><span class="line"> <span class="keyword">protected</span>:</span><br><span class="line">  <span class="built_in">string</span> m_name;</span><br><span class="line">  LogLevel m_level; <span class="comment">// 每个Channel都有自己的等级</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h6 id="ConsoleChannel"><a href="#ConsoleChannel" class="headerlink" title="ConsoleChannel"></a>ConsoleChannel</h6><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> ConsoleChannel::write(<span class="keyword">const</span> Logger &amp;logger, <span class="keyword">const</span> LogContextPtr &amp;logContext) &#123;</span><br><span class="line">  <span class="keyword">if</span> (m_level &gt; logContext-&gt;m_level) &#123;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  format(logger,<span class="built_in">std</span>::<span class="built_in">cout</span>,logContext, <span class="literal">true</span>,<span class="literal">true</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h6 id="FileChannel"><a href="#FileChannel" class="headerlink" title="FileChannel"></a>FileChannel</h6><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> FileChannel::write(<span class="keyword">const</span> Logger &amp;logger, <span class="keyword">const</span> LogContextPtr &amp;logContext) &#123;</span><br><span class="line">  <span class="keyword">if</span> (m_level &gt; logContext-&gt;m_level) &#123;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">if</span> (!m_fstream.is_open()) &#123;</span><br><span class="line">    open();</span><br><span class="line">  &#125;</span><br><span class="line">  format(logger, m_fstream, logContext, <span class="literal">false</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> FileChannel::open() &#123;</span><br><span class="line">  <span class="comment">// Ensure a path was set</span></span><br><span class="line">  <span class="keyword">if</span> (m_path.empty()) &#123;</span><br><span class="line">    <span class="keyword">throw</span> runtime_error(<span class="string">"Log file path must be set."</span>);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">// Open the file stream</span></span><br><span class="line">  m_fstream.close();</span><br><span class="line">  m_fstream.open(m_path.c_str(), ios::out | ios::app);</span><br><span class="line">  <span class="comment">// Throw on failure</span></span><br><span class="line">  <span class="keyword">if</span> (!m_fstream.is_open()) &#123;</span><br><span class="line">    <span class="keyword">throw</span> runtime_error(<span class="string">"Failed to open log file: "</span> + m_path);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">void</span> FileChannel::close() &#123;</span><br><span class="line">  m_fstream.close();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h6 id="SysLogChannel"><a href="#SysLogChannel" class="headerlink" title="SysLogChannel"></a>SysLogChannel</h6><p>Linux C中提供一套系统日记写入接口，包括三个函数：openlog，syslog和closelog。调用openlog是可选择的。如果不调用openlog，则在第一次调用syslog时，自动调用openlog。调用closelog也是可选择的，它只是关闭被用于与syslog守护进程通信的描述符。</p>
<p>其中openlog和closelog都是可选的。不过，通过调用openlog，我们可以指定ident参数。这样，ident将被加到每条日记记录中。</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;syslog.h&gt;   </span></span></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span>   </span></span><br><span class="line"><span class="function"></span>&#123;   </span><br><span class="line">    openlog(<span class="string">"testsyslog"</span>, LOG_CONS | LOG_PID, <span class="number">0</span>);   </span><br><span class="line">    syslog(LOG_USER | LOG_INFO, <span class="string">"syslog test message generated in program %s \n"</span>, argv[<span class="number">0</span>]);   </span><br><span class="line">    closelog();   </span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;   </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">void</span> SysLogChannel::write(<span class="keyword">const</span> Logger &amp;logger, <span class="keyword">const</span> LogContextPtr &amp;logContext) &#123;</span><br><span class="line">  <span class="keyword">if</span> (m_level &gt; logContext-&gt;m_level) &#123;</span><br><span class="line">    <span class="keyword">return</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">static</span> <span class="keyword">int</span> s_syslog_lev[<span class="number">10</span>];</span><br><span class="line">  s_syslog_lev[LTrace] = LOG_DEBUG;</span><br><span class="line">  s_syslog_lev[LDebug] = LOG_INFO;</span><br><span class="line">  s_syslog_lev[LInfo] = LOG_NOTICE;</span><br><span class="line">  s_syslog_lev[LWarn] = LOG_WARNING;</span><br><span class="line">  s_syslog_lev[LError] = LOG_ERR;</span><br><span class="line"></span><br><span class="line">  syslog(s_syslog_lev[logContext-&gt;m_level],<span class="string">"-&gt; %s %d\r\n"</span>,logContext-&gt;m_pFile,logContext-&gt;m_line);</span><br><span class="line">  syslog(s_syslog_lev[logContext-&gt;m_level], <span class="string">"## %s %s | %s %s\r\n"</span>, printTime(logContext-&gt;_tv).data(),</span><br><span class="line">         LOG_CONST_TABLE[logContext-&gt;m_level][<span class="number">2</span>], logContext-&gt;m_pFunction, logContext-&gt;str().c_str());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h6 id="AsyncLogWriter"><a href="#AsyncLogWriter" class="headerlink" title="AsyncLogWriter"></a>AsyncLogWriter</h6><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">AsyncLogWriter::AsyncLogWriter(Logger &amp;logger) : m_exit_flag(<span class="literal">false</span>),m_logger(logger) &#123;</span><br><span class="line">  m_thread = <span class="built_in">std</span>::make_shared&lt;thread&gt;([<span class="keyword">this</span>]() &#123; <span class="keyword">this</span>-&gt;run(); &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">AsyncLogWriter::~AsyncLogWriter() &#123;</span><br><span class="line">  m_exit_flag = <span class="literal">true</span>;</span><br><span class="line">  m_sem.post();</span><br><span class="line">  m_thread-&gt;join();</span><br><span class="line">  flushAll();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> AsyncLogWriter::write(<span class="keyword">const</span> LogContextPtr &amp;logContext) &#123;</span><br><span class="line">  &#123;</span><br><span class="line">    lock_guard&lt;mutex&gt; lock(m_mutex);</span><br><span class="line">    m_pending.emplace_back(logContext);</span><br><span class="line">  &#125;</span><br><span class="line">  m_sem.post();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> AsyncLogWriter::run() &#123;</span><br><span class="line">  <span class="keyword">while</span> (!m_exit_flag) &#123;</span><br><span class="line">    m_sem.wait();</span><br><span class="line">    flushAll();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">void</span> AsyncLogWriter::flushAll()&#123;</span><br><span class="line">  <span class="built_in">list</span>&lt;LogContextPtr&gt; tmp;</span><br><span class="line">  &#123;</span><br><span class="line">    lock_guard&lt;mutex&gt; lock(m_mutex);</span><br><span class="line">    tmp.swap(m_pending);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">const</span> <span class="keyword">auto</span> &amp; ctx : tmp)</span><br><span class="line">  &#123;</span><br><span class="line">    m_logger.writeChannels(ctx);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h4 id="ResourcePool循环池辅助类"><a href="#ResourcePool循环池辅助类" class="headerlink" title="ResourcePool循环池辅助类"></a>ResourcePool循环池辅助类</h4><p><strong>限制资源的总数，防止资源过多，每次析构时，会根据池中的数量，决定是放回池中，还是删除。</strong></p>
<h5 id="测试程序"><a href="#测试程序" class="headerlink" title="测试程序"></a>测试程序</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">string_imp</span> :</span> <span class="keyword">public</span> <span class="built_in">string</span> &#123;</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  <span class="keyword">template</span>&lt;<span class="keyword">typename</span> ...ArgTypes&gt;</span><br><span class="line">  string_imp(ArgTypes &amp;&amp;...args) : <span class="built_in">string</span>(<span class="built_in">std</span>::forward&lt;ArgTypes&gt;(args)...) &#123;</span><br><span class="line">    DebugL &lt;&lt; <span class="string">"创建string对象:"</span> &lt;&lt; <span class="keyword">this</span> &lt;&lt; <span class="string">" "</span> &lt;&lt; *<span class="keyword">this</span>;</span><br><span class="line">  &#125;;</span><br><span class="line">  ~string_imp() &#123;</span><br><span class="line">    WarnL &lt;&lt; <span class="string">"销毁string对象:"</span> &lt;&lt; <span class="keyword">this</span> &lt;&lt; <span class="string">" "</span> &lt;&lt; *<span class="keyword">this</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">  <span class="comment">//初始化日志</span></span><br><span class="line">  Logger::Instance().add(<span class="built_in">std</span>::make_shared&lt;ConsoleChannel&gt;());</span><br><span class="line">  Logger::Instance().setWriter(<span class="built_in">std</span>::make_shared&lt;AsyncLogWriter&gt;());</span><br><span class="line">  &#123;</span><br><span class="line">    <span class="comment">//大小为50的循环池</span></span><br><span class="line">    ResourcePool&lt;string_imp&gt; pool;</span><br><span class="line">    pool.setSize(<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">//获取一个对象,该对象将被主线程持有，并且不会被后台线程获取并赋值</span></span><br><span class="line">    <span class="keyword">auto</span> reservedObj = pool.obtain();</span><br><span class="line"></span><br><span class="line">    reservedObj.reset();</span><br><span class="line"></span><br><span class="line">    &#123;</span><br><span class="line">      WarnL &lt;&lt; <span class="string">"主线程打印:开始测试主动放弃循环使用功能"</span>;</span><br><span class="line"></span><br><span class="line">      <span class="built_in">std</span>::<span class="built_in">list</span>&lt;<span class="keyword">decltype</span>(pool)::ValuePtr&gt; objlist;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">4</span>; ++i) &#123;</span><br><span class="line">        reservedObj = pool.obtain();</span><br><span class="line">        <span class="built_in">string</span> str = StrPrinter &lt;&lt; i &lt;&lt; <span class="string">" "</span> &lt;&lt; (i % <span class="number">2</span> == <span class="number">0</span> ? <span class="string">"此对象将脱离循环池管理"</span> : <span class="string">"此对象将回到循环池"</span>);</span><br><span class="line">        reservedObj-&gt;assign(str);</span><br><span class="line">        reservedObj.quit(i % <span class="number">2</span> == <span class="number">0</span>);</span><br><span class="line">        objlist.emplace_back(reservedObj);</span><br><span class="line">      &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    ErrorL &lt;&lt; <span class="string">"循环结束没有放回池中的对象都被析构，进入池的对象不会析构⬆"</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  ErrorL &lt;&lt; <span class="string">"pool退出，析构pool中的对象⬆"</span>;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="shared-ptr-imp"><a href="#shared-ptr-imp" class="headerlink" title="shared_ptr_imp"></a>shared_ptr_imp</h5><ul>
<li>析构时，自动放回池或者删除</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">shared_ptr_imp</span> :</span> <span class="keyword">public</span> <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;C&gt; &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">	shared_ptr_imp() &#123;&#125;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * 构造智能指针</span></span><br><span class="line"><span class="comment">	 * @param ptr 裸指针</span></span><br><span class="line"><span class="comment">	 * @param weakPool 管理本指针的循环池</span></span><br><span class="line"><span class="comment">	 * @param quit 对接是否放弃循环使用</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	shared_ptr_imp(C *ptr,<span class="keyword">const</span> <span class="built_in">std</span>::weak_ptr&lt;ResourcePool_l&lt;C&gt; &gt; &amp;weakPool , <span class="keyword">const</span> <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;<span class="keyword">atomic_bool</span>&gt; &amp;quit) ;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/**</span></span><br><span class="line"><span class="comment">	 * 放弃或恢复回到循环池继续使用</span></span><br><span class="line"><span class="comment">	 * @param flag</span></span><br><span class="line"><span class="comment">	 */</span></span><br><span class="line">	<span class="function"><span class="keyword">void</span> <span class="title">quit</span><span class="params">(<span class="keyword">bool</span> flag = <span class="literal">true</span>)</span></span>&#123;</span><br><span class="line">		<span class="keyword">if</span>(_quit)&#123;</span><br><span class="line">			*_quit = flag;</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">	<span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;<span class="keyword">atomic_bool</span>&gt; _quit;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line">shared_ptr_imp&lt;C&gt;::shared_ptr_imp(C *ptr,</span><br><span class="line">								  <span class="keyword">const</span> <span class="built_in">std</span>::weak_ptr&lt;ResourcePool_l&lt;C&gt; &gt; &amp;weakPool ,</span><br><span class="line">								  <span class="keyword">const</span> <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;<span class="keyword">atomic_bool</span>&gt; &amp;quit ) :</span><br><span class="line">		<span class="built_in">shared_ptr</span>&lt;C&gt;(ptr,[weakPool,quit](C *ptr)&#123;</span><br><span class="line">			<span class="keyword">auto</span> strongPool = weakPool.lock(); <span class="comment">// 变成share_ptr</span></span><br><span class="line">			<span class="keyword">if</span> (strongPool &amp;&amp; !(*quit)) &#123;</span><br><span class="line">				<span class="comment">//循环池还在并且不放弃放入循环池 析构时自动释放</span></span><br><span class="line">				strongPool-&gt;recycle(ptr);</span><br><span class="line">			&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">				<span class="keyword">delete</span> ptr;</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;),_quit(quit) &#123;&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="ResourcePool"><a href="#ResourcePool" class="headerlink" title="ResourcePool"></a>ResourcePool</h5><ul>
<li>设置pool大小</li>
<li>获取元素</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ResourcePool</span> &#123;</span></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">   <span class="keyword">typedef</span> shared_ptr_imp&lt;C&gt; ValuePtr;</span><br><span class="line">   ResourcePool() &#123;</span><br><span class="line">         pool.reset(<span class="keyword">new</span> ResourcePool_l&lt;C&gt;());</span><br><span class="line">   &#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(SUPPORT_DYNAMIC_TEMPLATE)</span></span><br><span class="line">   <span class="keyword">template</span>&lt;<span class="keyword">typename</span> ...ArgTypes&gt;</span><br><span class="line">   ResourcePool(ArgTypes &amp;&amp;...args) &#123;</span><br><span class="line">      pool = <span class="built_in">std</span>::make_shared&lt;ResourcePool_l&lt;C&gt; &gt;(<span class="built_in">std</span>::forward&lt;ArgTypes&gt;(args)...);</span><br><span class="line">   &#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">//defined(SUPPORT_DYNAMIC_TEMPLATE)</span></span></span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">setSize</span><span class="params">(<span class="keyword">int</span> size)</span> </span>&#123; <span class="comment">// 设置资源池的大小</span></span><br><span class="line">      pool-&gt;setSize(size);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function">ValuePtr <span class="title">obtain</span><span class="params">()</span> </span>&#123; <span class="comment">// 获取一个元素</span></span><br><span class="line">      <span class="keyword">return</span> pool-&gt;obtain();</span><br><span class="line">   &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">   <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;ResourcePool_l&lt;C&gt; &gt; pool;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h5 id="ResourcePool-l"><a href="#ResourcePool-l" class="headerlink" title="ResourcePool_l"></a>ResourcePool_l</h5><ul>
<li>实现创建对象</li>
<li>获取对象</li>
<li>回收对象，池满删除</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ResourcePool_l</span>:</span> <span class="keyword">public</span> enable_shared_from_this&lt;ResourcePool_l&lt;C&gt; &gt; &#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">   <span class="keyword">typedef</span> shared_ptr_imp&lt;C&gt; ValuePtr;</span><br><span class="line">   <span class="keyword">friend</span> <span class="class"><span class="keyword">class</span> <span class="title">shared_ptr_imp</span>&lt;C&gt;;</span></span><br><span class="line">   ResourcePool_l() &#123;</span><br><span class="line">     <span class="comment">// 定义一个创建对象的指针</span></span><br><span class="line">      _allotter = []()-&gt;C* &#123;</span><br><span class="line">         <span class="keyword">return</span> <span class="keyword">new</span> C();</span><br><span class="line">      &#125;;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">if</span> defined(SUPPORT_DYNAMIC_TEMPLATE)</span></span><br><span class="line">   <span class="keyword">template</span>&lt;<span class="keyword">typename</span> ...ArgTypes&gt;</span><br><span class="line">   ResourcePool_l(ArgTypes &amp;&amp;...args) &#123;</span><br><span class="line">      _allotter = [args...]()-&gt;C* &#123;</span><br><span class="line">         <span class="keyword">return</span> <span class="keyword">new</span> C(args...);</span><br><span class="line">      &#125;;</span><br><span class="line">   &#125;</span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">//defined(SUPPORT_DYNAMIC_TEMPLATE)</span></span></span><br><span class="line"></span><br><span class="line">   ~ResourcePool_l()&#123;</span><br><span class="line">      <span class="built_in">std</span>::lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lck(_mutex);</span><br><span class="line">      _objs.for_each([](C *ptr)&#123;</span><br><span class="line">         <span class="keyword">delete</span> ptr;</span><br><span class="line">      &#125;);</span><br><span class="line">   &#125;</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">setSize</span><span class="params">(<span class="keyword">int</span> size)</span> </span>&#123;</span><br><span class="line">      _poolsize = size;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 如果资源池中没有元素，则创建一个，如果有，则取出一个</span></span><br><span class="line">   <span class="function">ValuePtr <span class="title">obtain</span><span class="params">()</span> </span>&#123;</span><br><span class="line">      <span class="built_in">std</span>::lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lck(_mutex);</span><br><span class="line">      C *ptr;</span><br><span class="line">      <span class="keyword">if</span> (_objs.size() == <span class="number">0</span>) &#123;</span><br><span class="line">         ptr = _allotter();</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">         ptr = _objs.front();</span><br><span class="line">         _objs.pop_front();</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> ValuePtr(ptr,<span class="keyword">this</span>-&gt;shared_from_this(),<span class="built_in">std</span>::make_shared&lt;<span class="keyword">atomic_bool</span>&gt;(<span class="literal">false</span>));</span><br><span class="line">   &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">   <span class="function"><span class="keyword">void</span> <span class="title">recycle</span><span class="params">(C *obj)</span> </span>&#123;</span><br><span class="line">      <span class="built_in">std</span>::lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lck(_mutex);</span><br><span class="line">      <span class="keyword">if</span> ((<span class="keyword">int</span>)_objs.size() &gt;= _poolsize) &#123;</span><br><span class="line">         <span class="keyword">delete</span> obj;</span><br><span class="line">         <span class="keyword">return</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      _objs.emplace_back(obj);</span><br><span class="line">   &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">   List&lt;C*&gt; _objs;</span><br><span class="line">   function&lt;C*(<span class="keyword">void</span>)&gt; _allotter;</span><br><span class="line">   mutex _mutex;</span><br><span class="line">   <span class="keyword">int</span> _poolsize = <span class="number">8</span>;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h4 id="ThreadPool线程池辅助类"><a href="#ThreadPool线程池辅助类" class="headerlink" title="ThreadPool线程池辅助类"></a>ThreadPool线程池辅助类</h4><h5 id="ThreadPool-ThreadGroup-TaskQueue"><a href="#ThreadPool-ThreadGroup-TaskQueue" class="headerlink" title="ThreadPool = ThreadGroup+TaskQueue"></a>ThreadPool = ThreadGroup+TaskQueue</h5><ul>
<li>ThreadPool 设置线程个数，</li>
<li>设置线程池的优先级</li>
<li>设置线程池是自动运行和手动运行 </li>
<li>插入线程池的最开始</li>
<li>调整单个线程的优先级</li>
<li>支持同步执行</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ThreadPool</span>:</span> <span class="keyword">public</span> TaskExecutor</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="keyword">enum</span> Priority</span><br><span class="line">    &#123;</span><br><span class="line">        PRIORITY_LOWEST = <span class="number">0</span>,</span><br><span class="line">        PRIORITY_LOW,</span><br><span class="line">        PRIORITY_NORMAL,</span><br><span class="line">        PRIORITY_HIGH,</span><br><span class="line">        PRIORITY_HIGHEST</span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//num:线程池线程个数</span></span><br><span class="line">    ThreadPool(<span class="keyword">int</span> num = <span class="number">1</span>,</span><br><span class="line">               Priority priority = PRIORITY_HIGHEST,</span><br><span class="line">               <span class="keyword">bool</span> autoRun = <span class="literal">true</span>)</span><br><span class="line">        :</span><br><span class="line">        _thread_num(num), _priority(priority)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">if</span> (autoRun) &#123;</span><br><span class="line">            start();</span><br><span class="line">        &#125;</span><br><span class="line">        _logger = Logger::Instance().shared_from_this();</span><br><span class="line">    &#125;</span><br><span class="line">    ~ThreadPool()</span><br><span class="line">    &#123;</span><br><span class="line">        shutdown();</span><br><span class="line">        wait();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//把任务打入线程池并异步执行</span></span><br><span class="line">    Task::<span class="function">Ptr <span class="title">async</span><span class="params">(TaskIn &amp;&amp;task, <span class="keyword">bool</span> may_sync = <span class="literal">true</span>)</span> override</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (may_sync &amp;&amp; _thread_group.is_this_thread_in()) &#123;</span><br><span class="line">            task();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">auto</span> ret = <span class="built_in">std</span>::make_shared&lt;Task&gt;(<span class="built_in">std</span>::move(task));</span><br><span class="line">        _queue.push_task(ret);</span><br><span class="line">        <span class="keyword">return</span> ret;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 放到最前面</span></span><br><span class="line">    Task::<span class="function">Ptr <span class="title">async_first</span><span class="params">(TaskIn &amp;&amp;task, <span class="keyword">bool</span> may_sync = <span class="literal">true</span>)</span> override</span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (may_sync &amp;&amp; _thread_group.is_this_thread_in()) &#123;</span><br><span class="line">            task();</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">nullptr</span>;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">auto</span> ret = <span class="built_in">std</span>::make_shared&lt;Task&gt;(<span class="built_in">std</span>::move(task));</span><br><span class="line">        _queue.push_task_first(ret);</span><br><span class="line">        <span class="keyword">return</span> ret;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">uint64_t</span> size()</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="keyword">return</span> _queue.size();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">static</span> <span class="keyword">bool</span> <span class="title">setPriority</span><span class="params">(Priority priority = PRIORITY_NORMAL,</span></span></span><br><span class="line"><span class="function"><span class="params">                            thread::native_handle_type threadId = <span class="number">0</span>)</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">int</span> Min = sched_get_priority_min(SCHED_OTHER);</span><br><span class="line">        <span class="keyword">if</span> (Min == <span class="number">-1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">int</span> Max = sched_get_priority_max(SCHED_OTHER);</span><br><span class="line">        <span class="keyword">if</span> (Max == <span class="number">-1</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">static</span> <span class="keyword">int</span> Priorities[] = &#123; Min, Min + (Max - Min) / <span class="number">4</span>, Min</span><br><span class="line">            + (Max - Min) / <span class="number">2</span>, Min + (Max - Min) * <span class="number">3</span>/ <span class="number">4</span>, Max &#125;;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">if</span> (threadId == <span class="number">0</span>) &#123;</span><br><span class="line">            threadId = pthread_self();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="class"><span class="keyword">struct</span> <span class="title">sched_param</span> <span class="title">params</span>;</span></span><br><span class="line">        params.sched_priority = Priorities[priority];</span><br><span class="line">        <span class="keyword">return</span> pthread_setschedparam(threadId, SCHED_OTHER, &amp;params) == <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">start</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (_thread_num &lt;= <span class="number">0</span>)</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        <span class="keyword">auto</span> total = _thread_num - _thread_group.size();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; total; ++i) &#123;</span><br><span class="line">            _thread_group.create_thread(bind(&amp;ThreadPool::run, <span class="keyword">this</span>));</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">run</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        ThreadPool::setPriority(_priority);</span><br><span class="line">        Task::Ptr task;</span><br><span class="line">        <span class="keyword">while</span> (<span class="literal">true</span>) &#123;</span><br><span class="line">            startSleep();</span><br><span class="line">            <span class="keyword">if</span> (!_queue.get_task(task)) &#123;</span><br><span class="line">                <span class="comment">//空任务，退出线程</span></span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            sleepWakeUp();</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                (*task)();</span><br><span class="line">                task = <span class="literal">nullptr</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">catch</span> (<span class="built_in">std</span>::exception &amp;ex) &#123;</span><br><span class="line">                ErrorL &lt;&lt; <span class="string">"ThreadPool执行任务捕获到异常:"</span> &lt;&lt; ex.what();</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">wait</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        _thread_group.join_all();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">shutdown</span><span class="params">()</span></span></span><br><span class="line"><span class="function">    </span>&#123;</span><br><span class="line">        _queue.push_exit(_thread_num);</span><br><span class="line">    &#125;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    TaskQueue&lt;Task::Ptr&gt; _queue;</span><br><span class="line">    thread_group _thread_group;</span><br><span class="line">    <span class="keyword">int</span> _thread_num;</span><br><span class="line">    Priority _priority;</span><br><span class="line">    Logger::Ptr _logger;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h6 id="TaskExecutor"><a href="#TaskExecutor" class="headerlink" title="TaskExecutor"></a>TaskExecutor</h6><ul>
<li>纯虚函数async</li>
</ul>
<h5 id="ThreadGroup-（创建就运行）"><a href="#ThreadGroup-（创建就运行）" class="headerlink" title="ThreadGroup （创建就运行）"></a>ThreadGroup （创建就运行）</h5><ul>
<li>可以判断当前线程是否属于线程池</li>
<li>添加线程create_thread 返回线程指针</li>
<li>移除线程remove_thread</li>
</ul>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ThreadGroup</span> &#123;</span></span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  ThreadGroup(ThreadGroup <span class="keyword">const</span> &amp;);</span><br><span class="line">  ThreadGroup &amp;<span class="keyword">operator</span>=(ThreadGroup <span class="keyword">const</span> &amp;);</span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  ThreadGroup() &#123;</span><br><span class="line">  &#125;</span><br><span class="line">  ~ThreadGroup() &#123;</span><br><span class="line">    _threads.clear();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">is_this_thread_in</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">auto</span> thread_id = this_thread::get_id();</span><br><span class="line">    <span class="keyword">if</span> (_thread_id == thread_id) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> _threads.find(thread_id) != _threads.end();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">is_thread_in</span><span class="params">(thread *thrd)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (!thrd) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">auto</span> it = _threads.find(thrd-&gt;get_id());</span><br><span class="line">    <span class="keyword">return</span> it != _threads.end();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">template</span>&lt;<span class="keyword">typename</span> F&gt;</span><br><span class="line">  <span class="function">thread *<span class="title">create_thread</span><span class="params">(F &amp;&amp;threadfunc)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">auto</span> thread_new = <span class="built_in">std</span>::make_shared&lt;thread&gt;(threadfunc);</span><br><span class="line">    _thread_id = thread_new-&gt;get_id();</span><br><span class="line">    _threads[_thread_id] = thread_new;</span><br><span class="line">    <span class="keyword">return</span> thread_new.get();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">remove_thread</span><span class="params">(thread *thrd)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">auto</span> it = _threads.find(thrd-&gt;get_id());</span><br><span class="line">    <span class="keyword">if</span> (it != _threads.end()) &#123;</span><br><span class="line">      _threads.erase(it);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">join_all</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">if</span> (is_this_thread_in()) &#123;</span><br><span class="line">      <span class="keyword">throw</span> runtime_error(<span class="string">"thread_group: trying joining itself"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">auto</span> &amp;it : _threads) &#123;</span><br><span class="line">      <span class="keyword">if</span> (it.second-&gt;joinable()) &#123;</span><br><span class="line">        it.second-&gt;join(); <span class="comment">//等待线程主动退出</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    _threads.clear();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">size_t</span> size() &#123;</span><br><span class="line">    <span class="keyword">return</span> _threads.size();</span><br><span class="line">  &#125;</span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  <span class="built_in">unordered_map</span>&lt;thread::id, <span class="built_in">std</span>::<span class="built_in">shared_ptr</span>&lt;thread&gt; &gt; _threads;</span><br><span class="line">  thread::id _thread_id;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h5 id="TaskQueue"><a href="#TaskQueue" class="headerlink" title="TaskQueue"></a>TaskQueue</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> T&gt;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TaskQueue</span> &#123;</span></span><br><span class="line"> <span class="keyword">public</span>:</span><br><span class="line">  <span class="comment">//打入任务至列队</span></span><br><span class="line">  <span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">push_task</span><span class="params">(C &amp;&amp;task_func)</span> </span>&#123;</span><br><span class="line">    &#123;</span><br><span class="line">      lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lock(_mutex);</span><br><span class="line">      _queue.emplace_back(<span class="built_in">std</span>::forward&lt;C&gt;(task_func));</span><br><span class="line">    &#125;</span><br><span class="line">    _sem.post();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">template</span>&lt;<span class="keyword">typename</span> C&gt;</span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">push_task_first</span><span class="params">(C &amp;&amp;task_func)</span> </span>&#123;</span><br><span class="line">    &#123;</span><br><span class="line">      lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lock(_mutex);</span><br><span class="line">      _queue.emplace_front(<span class="built_in">std</span>::forward&lt;C&gt;(task_func));</span><br><span class="line">    &#125;</span><br><span class="line">    _sem.post();</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//清空任务列队</span></span><br><span class="line">  <span class="function"><span class="keyword">void</span> <span class="title">push_exit</span><span class="params">(<span class="keyword">unsigned</span> <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    _sem.post(n);</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="comment">//从列队获取一个任务，由执行线程执行</span></span><br><span class="line">  <span class="function"><span class="keyword">bool</span> <span class="title">get_task</span><span class="params">(T &amp;tsk)</span> </span>&#123;</span><br><span class="line">    _sem.wait();</span><br><span class="line">    lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lock(_mutex);</span><br><span class="line">    <span class="keyword">if</span> (_queue.size() == <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">//改成右值引用后性能提升了1倍多！</span></span><br><span class="line">    tsk = <span class="built_in">std</span>::move(_queue.front());</span><br><span class="line">    _queue.pop_front();</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">uint64_t</span> size() <span class="keyword">const</span> &#123;</span><br><span class="line">    lock_guard&lt;<span class="keyword">decltype</span>(_mutex)&gt; lock(_mutex);</span><br><span class="line">    <span class="keyword">return</span> _queue.size();</span><br><span class="line">  &#125;</span><br><span class="line"> <span class="keyword">private</span>:</span><br><span class="line">  <span class="comment">//经过对比List,std::list,std::deque三种容器发现，</span></span><br><span class="line">  <span class="comment">//在i5-6200U单线程环境下，执行1000万个任务时，分别耗时1.3，2.4，1.8秒左右</span></span><br><span class="line">  <span class="comment">//所以此处我们替换成性能最好的List模板</span></span><br><span class="line">  <span class="built_in">list</span>&lt;T&gt; _queue;</span><br><span class="line">  <span class="keyword">mutable</span> mutex _mutex;</span><br><span class="line">  semaphore _sem;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>
    </div>

    
    
    
        
      

      <footer class="post-footer">
          
            
          
          <div class="post-tags">
            
              <a href="/tags/C-11/" rel="tag"># C++11</a>
            
          </div>
        

        

          <div class="post-nav">
            <div class="post-nav-next post-nav-item">
              
                <a href="/2019/06/25/MySQL数据库/" rel="next" title="MySQL数据库">
                  <i class="fa fa-chevron-left"></i> MySQL数据库
                </a>
              
            </div>

            <span class="post-nav-divider"></span>

            <div class="post-nav-prev post-nav-item">
              
                <a href="/2019/07/04/鱼骨图分析法/" rel="prev" title="鱼骨图分析法">
                  鱼骨图分析法 <i class="fa fa-chevron-right"></i>
                </a>
              
            </div>
          </div>
        
      </footer>
    
  </div>
  
  
  
  </article>

  </div>


          </div>
          

        </div>
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            文章目录
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            站点概览
          </li>
        </ul>
      

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-overview">

          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">XuQi</p>
  <div class="site-description motion-element" itemprop="description"></div>
</div>
  <nav class="site-state motion-element">
      <div class="site-state-item site-state-posts">
        
          <a href="/archives/">
        
          <span class="site-state-item-count">44</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
    
      
      
      <div class="site-state-item site-state-tags">
        
        
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
          
        
        <span class="site-state-item-count">30</span>
        <span class="site-state-item-name">标签</span>
        
      </div>
    
  </nav>



        </div>
      </div>
      <!--noindex-->
        <div class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
            
            
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#编码规范"><span class="nav-number">1.</span> <span class="nav-text">编码规范</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#禁止拷贝基类"><span class="nav-number">2.</span> <span class="nav-text">禁止拷贝基类</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#为什么禁用拷贝（复制）构造函数"><span class="nav-number">2.1.</span> <span class="nav-text">为什么禁用拷贝（复制）构造函数</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#StrPrinter-辅助类"><span class="nav-number">3.</span> <span class="nav-text">StrPrinter 辅助类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#Logger-辅助类"><span class="nav-number">4.</span> <span class="nav-text">Logger 辅助类</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#LogContextCapturer"><span class="nav-number">4.1.</span> <span class="nav-text">LogContextCapturer</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#LogContext"><span class="nav-number">4.2.</span> <span class="nav-text">LogContext</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Logger"><span class="nav-number">4.3.</span> <span class="nav-text">Logger</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#LogChannel"><span class="nav-number">4.4.</span> <span class="nav-text">LogChannel</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#ConsoleChannel"><span class="nav-number">4.4.1.</span> <span class="nav-text">ConsoleChannel</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#FileChannel"><span class="nav-number">4.4.2.</span> <span class="nav-text">FileChannel</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#SysLogChannel"><span class="nav-number">4.4.3.</span> <span class="nav-text">SysLogChannel</span></a></li><li class="nav-item nav-level-6"><a class="nav-link" href="#AsyncLogWriter"><span class="nav-number">4.4.4.</span> <span class="nav-text">AsyncLogWriter</span></a></li></ol></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#ResourcePool循环池辅助类"><span class="nav-number">5.</span> <span class="nav-text">ResourcePool循环池辅助类</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#测试程序"><span class="nav-number">5.1.</span> <span class="nav-text">测试程序</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#shared-ptr-imp"><span class="nav-number">5.2.</span> <span class="nav-text">shared_ptr_imp</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ResourcePool"><span class="nav-number">5.3.</span> <span class="nav-text">ResourcePool</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ResourcePool-l"><span class="nav-number">5.4.</span> <span class="nav-text">ResourcePool_l</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#ThreadPool线程池辅助类"><span class="nav-number">6.</span> <span class="nav-text">ThreadPool线程池辅助类</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#ThreadPool-ThreadGroup-TaskQueue"><span class="nav-number">6.1.</span> <span class="nav-text">ThreadPool = ThreadGroup+TaskQueue</span></a><ol class="nav-child"><li class="nav-item nav-level-6"><a class="nav-link" href="#TaskExecutor"><span class="nav-number">6.1.1.</span> <span class="nav-text">TaskExecutor</span></a></li></ol></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ThreadGroup-（创建就运行）"><span class="nav-number">6.2.</span> <span class="nav-text">ThreadGroup （创建就运行）</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#TaskQueue"><span class="nav-number">6.3.</span> <span class="nav-text">TaskQueue</span></a></li></ol></li></ol></div>
            

          </div>
        </div>
      <!--/noindex-->
      

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">XuQi</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v3.9.0</div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <a href="https://theme-next.org" class="theme-link" rel="noopener" target="_blank">NexT.Muse</a> v7.3.0</div>

        








        
      </div>
    </footer>
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
      </div>

    

  </div>

  
  <script src="/lib/jquery/index.js?v=3.4.1"></script>
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>

<script src="/js/utils.js?v=7.3.0"></script>
  <script src="/js/motion.js?v=7.3.0"></script>


  <script src="/js/schemes/muse.js?v=7.3.0"></script>


<script src="/js/next-boot.js?v=7.3.0"></script>




  




























  

  

  


  
  <script src="/js/scrollspy.js?v=7.3.0"></script>
<script src="/js/post-details.js?v=7.3.0"></script>


</body>
</html>
